Viet TP's notepage

Welcome!! Viet is a Microsoft Student Partner in Vietnam

Enjoy WPF: make TabControl in WPF look like Browser Tabs

This article discusses: This article uses the following technologies:
  • Using TabControl in WPF
  • Making CustomControl with UserControl template
  • DataBinding with Collection
WPF, XAML, C#

##Source code:

http://cid-82ca521511c25e79.skydrive.live.com/self.aspx/Blog%20files/SourceCode/WebTabs.rar

Nowaday, Web Browsers mostly use tabs to browse many pages in a single window. Last night, while I was developing a small application, I found a funny trick with TabControl. My app has many forms arranged in many TabItem objects. I want the TabControl load only some particular TabItem objects and hide the others. It’s necessary to use databinding. In this case, controls (TabItem objects) are also data, and I bind a control (TabControl.ItemsSource) to control-data collection. What a thought! :D

Using TabControl

TabControl, an UIControl, is a Control in which we add TabItem objects. We can declare it in XAML:

<TabControl>
   <TabItem Header="MyFirstPage">
      <TextBlock Text="First Page only contains a string" Margin="50"/>
   </TabItem>
   <TabItem Header="MySecondPage">
      <StackPanel Margin="20">
         <TextBlock Margin="10"
	     Text="Second Page contains a ItemContainer to have many controls in"
	     />
         <Button Content="Free Click!!!"/>
      </StackPanel>
   </TabItem>
   <TabItem Header="LastPage"/>
</TabControl>
12-12-2009 2-19-35 SA

As other controls that contain many child-controls, TabControl has a Property named Items – a collection of object. TabItem objects declared in XAML actually are added to this collection. And besides declaring the collection in design-time, we can use databinding with it in code-behind.

Making CustomControl with UserControl template

With UserControl template in Visual Studio, we have a tricky way to make a TabItem control with edited visual.

Add new UserControl to project: Right-click on the project name in Solution Explorer –> Add –> User Control.

In the dialog, enter Name: WebTab.xaml. VS create 2 new files (WebTab.xaml and WebTab.xaml.cs).

In file WebTab.xaml, UserControl’s root element is UserControl. The trick is that we can change it into TabItem and now we have a custom TabItem control.

I define a custom TabItem that the header has a TextBlock represent the title, and a button to close this tab in main window; the content of TabItem is a Frame control – a control contains a WebBrowser object represent web page.

<TabItem.Header>
     <DockPanel>
          <TextBlock x:Name="txtHeader" Text="{Binding Header}" DockPanel.Dock="Left" Margin="2"/>
          <Button Style="{StaticResource ExitTabButtonStyle}" Click="Button_Click"/>
     </DockPanel>
</TabItem.Header>
<TabItem.Content>
     <Frame x:Name="myFrame"/>
</TabItem.Content>

ExitTabButtonStyle is a simple Style I define in the <TabItem.Resources> collection and you can find it in source code attached.

In file WebTab.xaml.cs, I define a field named myParent to keep the collection contains this tab. And I create an event handler Button_Click to remove this tab when button is clicked.

DataBinding with Collection

Class used for data source of binding to collection is System.Collections.ObjectModel.ObservableCollection<Type>. The difference between ObservableCollection<> and other collections is that it notifies the UI when it’s properties change.

We bind the property TabControl.Items to the collection, and after that we cannot change property Items directly.

In Loaded event handler of main window, bind the property TabControl.Items to the collection:

void MyBrowser_Loaded(object sender, RoutedEventArgs e)
{
     myTabs.Items.Clear();
     myTabs.ItemsSource = webTabs;
}

Remember to attach the event handler in the constructor of main window.

        public MyBrowser()
        {
            InitializeComponent();
            KeyDown += new KeyEventHandler(MyBrowser_KeyDown);
            Loaded += new RoutedEventHandler(MyBrowser_Loaded);
        }

I attach KeyDown event handler to make some hotkey for creating new tab (Ctrl+T) and closing current tab (Ctrl+W or Ctrl+F4)

        void MyBrowser_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Key == Key.F4 || e.Key == Key.W) && (e.KeyboardDevice.Modifiers == ModifierKeys.Control))
            {
                WebTab wt = myTabs.SelectedItem as WebTab;
                if (wt != null)
                    webTabs.Remove(wt);
            }

            if (e.Key == Key.T && e.KeyboardDevice.Modifiers == ModifierKeys.Control)
            {
                WebTab wt = new WebTab();
                wt.myParent = webTabs;
                webTabs.Add(wt);
                myTabs.SelectedItem = wt;
            }
        }

In oder to make it looks like a browser, I declare a textbox and a button in main window to insert the address and navigate web pages.

Click event handler for the button is

        private void btnGO_Click(object sender, RoutedEventArgs e)
        {
            WebTab wt = myTabs.SelectedItem as WebTab;
            if (wt == null)
            {
                wt = new WebTab();
                webTabs.Add(wt);
                myTabs.SelectedItem = wt;
            }
            try
            {
                Uri mUri = new Uri(tbxAddress.Text);
                wt.myFrame.Source = mUri;
            }
            catch (System.Exception ex)
            {
                wt.myFrame.Content = ex.Message;
            }
        }

Results

08-01-2010 3-18-35 CH

 

This is not a good design. Just for fun!! :)

2 responses to “Enjoy WPF: make TabControl in WPF look like Browser Tabs

  1. Hương January 8, 2010 at 3:16 pm

    For your helping, I also used this trick in my assignment ;)). Thanks again :D. About assigning shorcut keys, how about using Command :)

  2. Việt January 12, 2010 at 6:52 am

    In bigger program, when catching event is complex, instead of catching KeyDown event in main window, we should use the Command program pattern to design in a better way. Hope someday I can see a blog post about Command in your blog ;)

Leave a comment